// Protocol sniffing - detect protocol from packet data

use std::io::Result;

#[derive(Debug, Clone, PartialEq)]
pub enum Protocol {
    Http,
    Https,
    Tls,
    Ssh,
    Unknown,
}

pub struct Sniffer;

impl Sniffer {
    pub fn sniff(data: &[u8]) -> Protocol {
        if data.len() < 4 {
            return Protocol::Unknown;
        }

        // HTTP
        if data.starts_with(b"GET ") || 
           data.starts_with(b"POST") || 
           data.starts_with(b"HEAD") ||
           data.starts_with(b"PUT ") ||
           data.starts_with(b"DELETE") {
            return Protocol::Http;
        }

        // TLS/HTTPS
        if data[0] == 0x16 && data[1] == 0x03 {
            return Protocol::Tls;
        }

        // SSH
        if data.starts_with(b"SSH-") {
            return Protocol::Ssh;
        }

        Protocol::Unknown
    }

    pub fn sniff_domain(data: &[u8]) -> Option<String> {
        // Try to extract SNI from TLS ClientHello
        if Self::sniff(data) == Protocol::Tls {
            return Self::extract_sni(data);
        }

        // Try to extract Host from HTTP
        if Self::sniff(data) == Protocol::Http {
            return Self::extract_http_host(data);
        }

        None
    }

    fn extract_sni(data: &[u8]) -> Option<String> {
        // Simplified SNI extraction
        // TODO: Implement full TLS ClientHello parsing
        None
    }

    fn extract_http_host(data: &[u8]) -> Option<String> {
        let s = String::from_utf8_lossy(data);
        for line in s.lines() {
            if line.to_lowercase().starts_with("host:") {
                return Some(line[5..].trim().to_string());
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_sniff_http() {
        let data = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
        assert_eq!(Sniffer::sniff(data), Protocol::Http);
    }

    #[test]
    fn test_sniff_tls() {
        let data = &[0x16, 0x03, 0x01, 0x00, 0x00];
        assert_eq!(Sniffer::sniff(data), Protocol::Tls);
    }
}
